#include "usb_cmd.h"
#include "file_system.h"

extern osThreadId comm_taskHandle;
Message_manager message_manager = {.message_num = 0,.manager_state = WAIT_MESSAGE, .allow_send = false};

void send_file_all_data(File_Struct* file, Data_from data_from);

void message_queue_put(Cmd_Message_pack pack){
    if(message_manager.message_num < 10){
        message_manager.manager_state = HANDLE_MESSAGE_QUEUE;
        message_manager.message_pack_queue[message_manager.message_num] = pack;
        message_manager.data_from = pack.data_from;
        message_manager.message_num ++;
    }
}

Cmd_Message_pack message_queue_pop(void){
    Cmd_Message_pack temp = {.avilable = false};
    if(message_manager.message_num > 0){
        temp = message_manager.message_pack_queue[0];
        for(int i=0;i< message_manager.message_num - 1;i++){
            message_manager.message_pack_queue[i] = message_manager.message_pack_queue[i + 1];
        }
        message_manager.message_num--;
        temp.avilable = true;
    }
    return temp;
}

void message_queue_handle(void){
    switch (message_manager.manager_state)
    {
		Cmd_Message_pack ret;
    case WAIT_MESSAGE:
				if(message_manager.message_num >0){
					message_manager.manager_state = HANDLE_MESSAGE_QUEUE;
				}else{
					osThreadSuspend(comm_taskHandle);
				}
        break;
    case HANDLE_MESSAGE_QUEUE:
        ret = message_queue_pop();
        if(ret.avilable){
					message_handle(&ret);
        }
				if(message_manager.message_num == 0){
					message_manager.manager_state = WAIT_MESSAGE;
				}
        break;
    default:
        break;
    }
}


void message_handle(Cmd_Message_pack* pack){
    if(pack->data_length > 0){
        if(pack->message_in[0] == RECV_HEADER && pack->message_in[pack->data_length - 1] == RECV_TAIL){
            uint8_t recv_id = pack->message_in[1];
            uint8_t temp_send_data[256];
						message_manager.to_send_pack.data_from = pack->data_from;
            switch(recv_id){               
                case RECV_ID_CHECK:
										log_system.start_monitor = false;
                    message_manager.to_send_pack.data_length = 3;
										temp_send_data[0] = SEND_HEADER;
										temp_send_data[1] = SEND_ID_CHECK;
										temp_send_data[2] = SEND_TAIL;
                    memcpy(&message_manager.to_send_pack.message_in[0], &temp_send_data[0], message_manager.to_send_pack.data_length);
                    message_manager.allow_send = true;
                    break;
                case RECV_ID_INDEX:
										send_file_index(pack->data_from);
                    break;
                case RECV_ID_GET_LOG:
										send_target_log_data((pack->message_in[2] | (pack->message_in[3] << 8)), pack->data_from);
                    break;
								case RECV_ID_SET_PARAM:
										update_param_data(&pack->message_in[2], pack->data_length - 3);
										break;
								case RECV_ID_OPEN_NEW_N_LOG:
										open_new_normal_log();
										break;
								case RECV_ID_SET_N_LOG:
										set_normal_log((pack->message_in[2] | (pack->message_in[3] << 8)));
										break;
								case RECV_ID_WRITE_DATA_TO_NORMAL:
										write_data_to_current_normal(&pack->message_in[2], pack->data_length - 3);
										break;
								case RECV_ID_CLEAR_CURRENT_N_LOG:
										clear_current_nlog();
										break;
								case RECV_ID_RESET_FS:
										let_file_system_init();
										break;
                case RECV_ID_ONLINE_MONITOR:
                    online_send_monitor_data_flag_change(pack->message_in[2], pack->data_from);
                    break;
								case RECV_ID_PARAM_INIT:
										param_init();
										break;
								case RECV_ID_RESET_DART:
										reset_dart();
										break;
                default:
                    break;
            }
            if(message_manager.allow_send){
                if(pack->data_from == USB){
                    usb_data_send(&message_manager.to_send_pack.message_in[0], message_manager.to_send_pack.data_length);
                }
                else{
                    huart_send(&huart1_usart_handle, &message_manager.to_send_pack.message_in[0], message_manager.to_send_pack.data_length);
				}
                message_manager.allow_send = false;
            }
        }
    }
}

void online_send_monitor_data_flag_change(uint8_t flag, Data_from data_from){
    if(flag == 1){
        log_system.start_monitor = true;
    }else{
        log_system.start_monitor = false;
    }
    log_system.data_from_raw = (uint8_t )data_from;
}

void clear_current_nlog(){
	File_Struct file = open_file(BY_BOTH, NORMAL_FILE, now_normal_log_id);
	if(file.init_if && file.file_state == OPEN){
		clear_file(&file);
	}
}

void write_data_to_current_normal(uint8_t* raw_data, uint8_t data_len){
	File_Struct file = open_file(BY_BOTH, NORMAL_FILE, now_normal_log_id);
	if(file.init_if && file.file_state == OPEN){
		file_write(&file, raw_data, data_len);
		close_file(&file);
	}
}

void set_normal_log(uint16_t log_id){
	File_Struct file = open_file(BY_BOTH, NORMAL_FILE, log_id);
	if(file.init_if && file.file_state == OPEN){
		close_file(&file);
		uint8_t raw_data[2] = {log_id & 0xFF, (log_id >> 8) & 0xFF}; 
		File_Struct temp_file = open_file(BY_ID, SETTINGS_FILE, 0);
		if(temp_file.init_if && temp_file.file_state == OPEN){
			if(NOW_NORMAL_LOG_ID < setting_variables.now_num){
				uint8_t this_time_data_size = SIZEOF(setting_variables.pack[NOW_NORMAL_LOG_ID].type);
				uint16_t file_offset = get_setting_index_offset(NOW_NORMAL_LOG_ID);
				file_write_at(&temp_file, &raw_data[0], this_time_data_size, 2 + file_offset);
				now_normal_log_id = log_id;
				log_system.log_system_state = PARAM_INIT;
			}
		}
	}
}

bool write_normal_log(void *arg){
	(void)arg;
	bool ret = false;
	uint16_t last_log_id = file_system.loader_info.file_num - 1;
	uint8_t raw_data[2] = {last_log_id & 0xFF, (last_log_id >> 8) & 0xFF}; 
	File_Struct temp_file = open_file(BY_ID, SETTINGS_FILE, 0);
	File_Struct nor_file = open_file(BY_BOTH, NORMAL_FILE, last_log_id);
	if(temp_file.init_if && temp_file.file_state == OPEN && nor_file.init_if && nor_file.file_state == OPEN){
		if(NOW_NORMAL_LOG_ID < setting_variables.now_num){
			uint8_t this_time_data_size = SIZEOF(setting_variables.pack[NOW_NORMAL_LOG_ID].type);
			uint16_t file_offset = get_setting_index_offset(NOW_NORMAL_LOG_ID);
			file_write_at(&temp_file, &raw_data[0], this_time_data_size, 2 + file_offset);
			now_normal_log_id = last_log_id;
			ret = true;
			log_system.log_system_state = PARAM_INIT;
		}
	}
	return ret;
}

void open_new_normal_log(){
	create_file(NORMAL_FILE);
	now_normal_log_id = file_system.loader_info.file_num - 1;
	REGISTER_FUNC(&write_normal_log, 1000);
}

void param_init(void){
	File_Struct setting_file = open_file(BY_ID, SETTINGS_FILE, 0);
	clear_file(&setting_file);
	file_system.file_system_state = CHECK_FILE_SYSTEM;
	close_file(&setting_file);
	log_system.next_state = WAIT_FILE_SYSTEM_IDLE;
}

void let_file_system_init(){
	file_system.file_system_init = true;
}



void send_file_index(Data_from data_from){
	update_loader_info();
	uint16_t file_num = file_system.loader_info.file_num;
	uint16_t file_num_left = file_num;
	message_manager.to_send_pack.message_in[0] = SEND_HEADER;
	message_manager.to_send_pack.message_in[1] = SEND_ID_INDEX;
	message_manager.to_send_pack.message_in[2] = file_num & 0xFF;
	message_manager.to_send_pack.message_in[3] = (file_num >> 8) & 0xFF;
	uint8_t	cut_pieces = file_num / 250 + 1;
	for(int i=0;i< cut_pieces; i++){
		if(i == cut_pieces - 1){
			message_manager.to_send_pack.message_in[4] = 0;
		}else{
			message_manager.to_send_pack.message_in[4] = 1;
		}
		uint8_t this_time_write_len = 0;
		if(file_num_left > 250){
			this_time_write_len = 250;
		}else{
			this_time_write_len = file_num_left;
		}
		
		for(int j=0 + i*250; j< this_time_write_len + i*250; j++){
			get_flash_data(&message_manager.to_send_pack.message_in[j + 5], get_file_id_to_start_addr(j), 1);
		}
		message_manager.to_send_pack.message_in[5 + this_time_write_len] = SEND_TAIL;
		if(data_from == USB){
			usb_data_send(&message_manager.to_send_pack.message_in[0], 6 + this_time_write_len);
		}
        else{
            huart_send(&huart1_usart_handle, &message_manager.to_send_pack.message_in[0], 6 + this_time_write_len);
        }
		osDelay(10);
	}
}


void send_target_log_data(uint16_t tar_log_id, Data_from data_from){
	File_Struct temp_file = open_file(BY_ID, NORMAL_FILE, tar_log_id);
	if(temp_file.init_if && temp_file.file_state == OPEN){
		send_file_all_data(&temp_file, data_from);
	}
	close_file(&temp_file);
}

uint8_t watch_bufs[10];

void send_file_all_data(File_Struct* file, Data_from data_from){
	uint16_t next_piece_id = 0;
	uint16_t now_piece_id = file->file_loader_info.start_piece_id;
	message_manager.to_send_pack.message_in[0] = SEND_HEADER;
	message_manager.to_send_pack.message_in[1] = SEND_ID_SEND_LOG;
	message_manager.to_send_pack.message_in[2] = 0x00;
	message_manager.to_send_pack.message_in[3] = SEND_TAIL;
	if(data_from == USB){
		usb_data_send(&message_manager.to_send_pack.message_in[0], 4);
	}
    else{
        huart_send(&huart1_usart_handle, &message_manager.to_send_pack.message_in[0], 4);
    }
	osDelay(5);
	
	uint8_t read_offset = 0;
	if(file->file_loader_info.file_type == SETTINGS_FILE){
		read_offset = 2;
	}
	while(next_piece_id != 0xFFFF){
		uint32_t ret = file_read_piece(file, &message_manager.to_send_pack.message_in[3], now_piece_id, read_offset);
		next_piece_id = (ret & 0xFFFF);
		uint8_t this_page_size = (ret >> 16) & 0xFF;
		message_manager.to_send_pack.message_in[2] = 1;
		message_manager.to_send_pack.message_in[3 + this_page_size] = SEND_TAIL;
		message_manager.to_send_pack.data_length = 4 + this_page_size;
		watch_bufs[0] = file->file_loader_info.file_id;
		watch_bufs[1] = file->file_loader_info.start_piece_id;
		watch_bufs[2] = ret;
		if(data_from == USB){
			usb_data_send(&message_manager.to_send_pack.message_in[0], 4 + this_page_size);
		}
        else{
            huart_send(&huart1_usart_handle, &message_manager.to_send_pack.message_in[0], 4 + this_page_size);
        }
		if(next_piece_id == now_piece_id){
			clear_file(file);
			reset_dart();
			break;
		}
		now_piece_id = next_piece_id;
		read_offset = 0;
		if(data_from == USB){
			osDelay(5);
		}
		else{
			osDelay(10);
		}
	}
	
	message_manager.to_send_pack.message_in[2] = 0x02;
	message_manager.to_send_pack.message_in[3] = SEND_TAIL;
	if(data_from == USB){
		usb_data_send(&message_manager.to_send_pack.message_in[0], 4);
	}
    else{
        huart_send(&huart1_usart_handle, &message_manager.to_send_pack.message_in[0], 4);
    }
}
